﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml;
using ServiciosGeograficos.Modelo;
using ServiciosGeograficos.Servicios;
using ServiciosGeograficos.Reconocimiento;

namespace ServicioProcesarSMS
{
    /// <summary>
    /// Summary description for Service1
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class ProcesarSMS : System.Web.Services.WebService
    {
        private const string DELIMITADOR = "#";

        [WebMethod]
        public DatosSMSProcesado ProcesarDatosSMS(string mensaje)
        {
            string mensajeError = null;

            //verifico que no sea vacio
            mensaje = VerificarNuloOVacio(mensaje, out mensajeError);
            if (mensajeError != null)
            {
                return CrearRetornoSMS(mensajeError);
            }

            //separo los items y verifico que tenga el minimo de items necesarios
            string[] strArray = mensaje.Split(new string[] { DELIMITADOR }, StringSplitOptions.RemoveEmptyEntries);
            if (strArray.Count() < 2)
            {
                mensajeError = "Mensaje incompleto, no ingresaste la cantidad de información necesaria";

                return CrearRetornoSMS(mensajeError);
            }

            //obtengo el tipo de mensaje
            int tipoMensaje = ObtenerTipoMensaje(strArray[0], out mensajeError);
            if (mensajeError != null)
            {
                return CrearRetornoSMS(mensajeError);
            }

            DatosSMSEntrada smsEntrada = new DatosSMSEntrada();
            smsEntrada.TipoMensaje = tipoMensaje;

            switch (tipoMensaje)
            {
                case 0: //esquina (calle - calle) - linea - destino
                    if (strArray.Length < 5)
                        mensajeError = "La cantidad de parametros en un mensaje de tipo: Esquina - Linea - Destino, debe ser 5";
                    else
                    {
                        smsEntrada.Calle1 = strArray[1];
                        smsEntrada.Calle2 = strArray[2];
                        smsEntrada.Linea = strArray[3];
                        smsEntrada.Destino = strArray[4];
                    }
                    break;
                case 1: //calle - numero de puerta - linea - destino
                    if (strArray.Length < 5)
                        mensajeError = "La cantidad de parámetros en un mensaje de tipo: " +
                            "Calle - Numero de Puerta - Linea - Destino, debe ser 5";
                    else
                    {
                        smsEntrada.Calle1 = strArray[1];
                        smsEntrada.NumeroPuerta = strArray[2];
                        smsEntrada.Linea = strArray[3];
                        smsEntrada.Destino = strArray[4];
                    }
                    break;
                case 2: //idParada - linea
                    int idParada;
                    if (strArray.Length < 3)
                        mensajeError = "La cantidad de parámetros en un mensaje de tipo: "
                        + "ID Parada - Linea, debe ser 3";
                    else if (int.TryParse(strArray[1], out idParada))
                    {
                        smsEntrada.IdParada = idParada;
                        smsEntrada.Linea = strArray[2];
                    }
                    else
                    {
                        mensajeError = "El identificador de parada "
                        + strArray[1] + " no es correcto";
                    }
                    break;
                case 3:
                    if (strArray.Length < 2)
                        mensajeError = "La cantidad de parámetros en un mensaje de tipo: "
                        + "ID Parada, debe ser 2";
                    else if (int.TryParse(strArray[1], out idParada))
                    {
                        smsEntrada.IdParada = idParada;
                    }
                    else
                    {
                        mensajeError = "El identificador de parada "
                        + strArray[1] + " no es correcto";
                    }
                    break;
                default:
                    mensajeError = "El tipo de mensaje no es valido";
                    break;
            }
            if (mensajeError != null)
            {
                return CrearRetornoSMS(mensajeError);
            }

            //ubico la parada
            Retorno datosUbicarParada = UbicarParada(smsEntrada);

            return CrearRetornoSMS(datosUbicarParada, smsEntrada);
        }

        /// <summary>
        /// Crear retorno para caso de datos sin error
        /// </summary>
        /// <param name="datosUbicarParada"></param>
        /// <returns></returns>
        private DatosSMSProcesado CrearRetornoSMS(Retorno datosUbicarParada, DatosSMSEntrada smsEntrada)
        {
            string mensaje;
            switch (smsEntrada.TipoMensaje)
            {
                case 0: //esquina (calle - calle) - linea - destino
                    if (!datosUbicarParada.datosUbicados)
                    {
                        if (datosUbicarParada.tipoError == Servicios.PROBLEMA_CALLE1)
                        {
                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaCalle1))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para la calle: "
                                    + smsEntrada.Calle1;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Calle1 + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaCalle1);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_CALLE2)
                        {

                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaCalle2))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para la calle: "
                                    + smsEntrada.Calle2;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Calle2 + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaCalle2);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_LINEA)
                        {
                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaLinea))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para la línea: "
                                    + smsEntrada.Linea;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Linea + "-" + smsEntrada.Destino + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaLinea);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_DESTINO)
                        {
                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaLinea))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para el destino: "
                                    + smsEntrada.Linea;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Linea + "-" + smsEntrada.Destino + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaLinea);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_CALLES_NO_SE_CRUZAN)
                        {
                            mensaje = "La intersección que ingresaste no existe!";
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_ID_PARADA)
                        {
                            mensaje = string.Format(
                                "El identificador de parada '{0}' no es correcto",
                                smsEntrada.IdParada);
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_ID_PARADA_LINEA_DESTINO)
                        {
                            mensaje = "La línea con destino que ingresaste no pasa por la parada que ingresaste";
                        }
                        else
                        {
                            mensaje = "No pudimos ubicar los datos que ingresaste";
                        }
                        return CrearRetornoSMS(mensaje);
                    }
                    else
                    {
                        return CrearRetornoSMS(true, (short)smsEntrada.TipoMensaje, string.Empty,
                            datosUbicarParada.idParada, datosUbicarParada.idLinea);
                    }
                case 1: //calle - numero de puerta - linea - destino
                    if (!datosUbicarParada.datosUbicados)
                    {
                        if (datosUbicarParada.tipoError == Servicios.PROBLEMA_CALLE1)
                        {
                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaCalle1))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para la calle: "
                                    + smsEntrada.Calle1;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Calle1 + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaCalle1);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_LINEA)
                        {
                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaLinea))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para la línea: "
                                    + smsEntrada.Linea;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Linea + "-" + smsEntrada.Destino + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaLinea);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_DESTINO)
                        {
                            if (string.IsNullOrEmpty(datosUbicarParada.sugerenciaLinea))
                            {
                                mensaje = "No entendimos ni encontramos sugerencias para el destino: "
                                    + smsEntrada.Linea;
                            }
                            else
                            {
                                mensaje = "En vez de " + smsEntrada.Linea + "-" + smsEntrada.Destino + " quisiste decir: ";
                                mensaje += ProcesarSugerencia(datosUbicarParada.sugerenciaLinea);
                                mensaje += "?";
                            }
                        }
                        else if (datosUbicarParada.tipoError == Servicios.PROBLEMA_NUMERO_PUERTA_NO_EXISTE)
                        {
                            mensaje = string.Format(
                                "No pudimos ubicar  el número de puerta {0} en {1}. Tambien podés intentar con una esquina.",
                                smsEntrada.NumeroPuerta, smsEntrada.Calle1);
                            return CrearRetornoSMS(mensaje);
                        }
                        else
                        {
                            mensaje = "No pudimos ubicar los datos que ingresaste";
                        }
                        return CrearRetornoSMS(mensaje);
                    }
                    else
                    {
                        return CrearRetornoSMS(true, smsEntrada.TipoMensaje, string.Empty,
                            datosUbicarParada.idParada, datosUbicarParada.idLinea);
                    }
                case 2: //idParada - linea - destino
                    if (!datosUbicarParada.datosUbicados)
                        return CrearRetornoSMS("La parada o la línea no existen");
                    else if (!string.IsNullOrEmpty(datosUbicarParada.sugerenciaLinea))
                    {
                        mensaje = "En vez de " + smsEntrada.Linea + " quisiste decir: " +
                            ProcesarSugerencia(datosUbicarParada.sugerenciaLinea);
                        return CrearRetornoSMS(mensaje);
                    }
                    else
                    {
                        return CrearRetornoSMS(true, smsEntrada.TipoMensaje, string.Empty,
                            datosUbicarParada.idParada, datosUbicarParada.idLinea);
                    }
                case 3:
                    if (!datosUbicarParada.datosUbicados)
                    {
                        mensaje = "La parada que ingresaste no es válida!";
                        return CrearRetornoSMS(mensaje);
                    }
                    else
                    {
                        mensaje = "Te podes tomar: " 
                            + ProcesarSugerencia(datosUbicarParada.sugerenciaLinea);
                        return CrearRetornoSMS(true, smsEntrada.TipoMensaje, mensaje,
                            datosUbicarParada.idParada, datosUbicarParada.idLinea);
                    }
                default:
                    mensaje = "El tipo de mensaje no es valido";
                    return CrearRetornoSMS(mensaje);
            }

        }

        private string ProcesarSugerencia(string sugerencias)
        {
            string sugerenciaProcesada = null;

            if (sugerencias != null)
            {
                string[] arraySugerencias = sugerencias.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string sugerencia in arraySugerencias)
                {
                    if (sugerenciaProcesada == null)
                        sugerenciaProcesada = sugerencia;
                    else
                    {
                        sugerenciaProcesada += " ó " + sugerencia;
                    }
                }
            }

            return sugerenciaProcesada;
        }

        /// <summary>
        /// Crea el retorno para datos con error
        /// </summary>
        /// <param name="mensajeError"></param>
        /// <returns></returns>
        private DatosSMSProcesado CrearRetornoSMS(string mensajeError)
        {
            return CrearRetornoSMS(false, null, mensajeError, null, null);
        }

        private DatosSMSProcesado CrearRetornoSMS(bool esCorrecto, int? tipoMensaje, string mensaje,
            int? idParada, int? idLinea)
        {
            DatosSMSProcesado datos = new DatosSMSProcesado();
            if (!esCorrecto)
                datos.TipoRetorno = (short)EnumTipoMensajeRetorno.DatosNoUbicados;
            else if (tipoMensaje == 3)
                datos.TipoRetorno = (short)EnumTipoMensajeRetorno.LineasDeParadaUbicados;
            else
                datos.TipoRetorno = (short)EnumTipoMensajeRetorno.LineasYParadasUbicadas;

            
            if (esCorrecto)
            {
                datos.IdParada = idParada;
                datos.IdLinea = idLinea;
            }
            else
            {
                datos.Mensaje = mensaje;
            }

            return datos;
        }

        private Retorno UbicarParada(DatosSMSEntrada smsEntrada)
        {
            Servicios serviciosGeograficos = new Servicios();
            int idParada = smsEntrada.IdParada == null ? -1 : (int)smsEntrada.IdParada;

            Retorno retorno = serviciosGeograficos.ubicarParada(smsEntrada.TipoMensaje, smsEntrada.Calle1,
                smsEntrada.Calle2, smsEntrada.Linea, smsEntrada.Destino,
                smsEntrada.NumeroPuerta, idParada);

            return retorno;
        }

        private string VerificarNuloOVacio(string mensaje, out string mensajeError)
        {
            mensajeError = null;

            if ((mensaje != null) && (mensaje.Trim() != string.Empty))
            {
                mensaje = mensaje.Trim();
                return mensaje;
            }
            else
                mensajeError = "El mensaje es vacio!";

            return null;
        }

        private int ObtenerTipoMensaje(string mensaje, out string mensajeError)
        {
            mensajeError = null;
            int tipoMensaje = -1;
            if (!int.TryParse(mensaje, out tipoMensaje))
            {
                mensajeError = "El mensaje no tiene el campo Tipo De Mensaje";
            }

            return tipoMensaje;
        }

    }
}
